﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace mirror
{
    class cVFXExplosion3D : cVFXBase
    {

        // Random number generator for the fire effect.
        Random random = new Random();

        float mRadius;
        float mRadiusMultiplier;
        float mDuration;
        Vector3 mPosition;

        ExplosionParticleSystem3D explosion3D;
        ExplosionSmokeParticleSystem3D explosionSmoke3D;
        ParticleProjectile3D projectile3D;
        ProjectileTrailParticleSystem3D projectileSmoke3D;
        SmokePlumeParticleSystem3D smokePlume3D;
        FireParticleSystem3D fire3D;

        bool mEnableExplosion = true;
        bool mEnableExplosionSmoke = false;
        bool mEnableProjectile = false;
        bool mEnableSmokePlume = false;
        bool mEnableFire = false;
        

        public cVFXExplosion3D(Vector3 zPosition)
            : this(zPosition, 2.0f, 1.25f)
        {
        }

        public cVFXExplosion3D(Vector3 zPosition, float zRadiusMultiplier, float zDuration)
        {
            mPosition = zPosition;
            mRadiusMultiplier = zRadiusMultiplier;
            mDuration = zDuration;

            ParticleStart();

        }

        //  Return true if the effect is still active, otherwise it will be removed.
        public override bool Update(GameTime zGameTime)
        {

            float dt = (float)zGameTime.ElapsedGameTime.TotalSeconds;

            base.Update(zGameTime);

            float effectDuration = mDuration;

            float minRadius = 1.0f * mRadiusMultiplier;
            float maxRadius = 2.2f * mRadiusMultiplier;
            float lerp = mTimeActive / effectDuration;
            mRadius = ((1.0f - lerp) * minRadius) + (lerp * maxRadius);

            if (mTimeActive > effectDuration)
            {
                return false;
            }

            if (mEnableExplosion)
            {
                if (lerp < 0.3f)
                {
                    explosion3D.AddParticle(mPosition, Vector3.Zero);
                }
                explosion3D.Update(zGameTime);
            }

            if (mEnableExplosionSmoke)
            {
                explosionSmoke3D.Update(zGameTime);
                explosionSmoke3D.AddParticle(mPosition, Vector3.Zero);
            }

            if (mEnableProjectile)
            {
                projectile3D.Update(zGameTime);
                //projectile3D.AddParticle(mPosition, Vector3.Zero);
            }

            if (mEnableSmokePlume)
            {
                smokePlume3D.Update(zGameTime);
                smokePlume3D.AddParticle(mPosition, Vector3.Zero);
            }

            if (mEnableFire)
            {

                const int fireParticlesPerFrame = 20;

                // Create a number of fire particles, randomly positioned around a circle.
                for (int i = 0; i < fireParticlesPerFrame; i++)
                {
                    fire3D.AddParticle(RandomPointOnCircle() + mPosition, Vector3.Zero);
                }

                // Create one smoke particle per frmae, too.
               // smokePlumeParticles.AddParticle(RandomPointOnCircle(), Vector3.Zero);

                fire3D.Update(zGameTime);
                fire3D.AddParticle(mPosition, Vector3.Zero);
            }

            return true;
        }

        public override void Draw()
        {
            base.Draw();

            if (mEnableExplosion)
            {
                explosion3D.SetCamera(Camera.Instance.ViewMatrix, Camera.Instance.ProjectionMatrix);
                explosion3D.Draw();
            }

            if (mEnableExplosionSmoke)
            {
                explosionSmoke3D.SetCamera(Camera.Instance.ViewMatrix, Camera.Instance.ProjectionMatrix);
                explosionSmoke3D.Draw();
            }

            if (mEnableProjectile)
            {
                projectileSmoke3D.SetCamera(Camera.Instance.ViewMatrix, Camera.Instance.ProjectionMatrix);
                projectileSmoke3D.Draw();
            }

            if (mEnableSmokePlume)
            {
                smokePlume3D.SetCamera(Camera.Instance.ViewMatrix, Camera.Instance.ProjectionMatrix);
                smokePlume3D.Draw();
            }
            
            if (mEnableFire)
            {
                fire3D.SetCamera(Camera.Instance.ViewMatrix, Camera.Instance.ProjectionMatrix);
                fire3D.Draw();
            }

            //  Ugg.Ugg.Instance.AddSphere(mPosition, mRadius, Color.Yellow);
        }

        public void ParticleStart()
        {
            explosion3D = new ExplosionParticleSystem3D();
            explosion3D.Initialize();
            explosion3D.LoadContent();

            explosionSmoke3D = new ExplosionSmokeParticleSystem3D();
            explosionSmoke3D.Initialize();
            explosionSmoke3D.LoadContent();

            projectileSmoke3D = new ProjectileTrailParticleSystem3D();
            projectileSmoke3D.Initialize();
            projectileSmoke3D.LoadContent();

            projectile3D = new ParticleProjectile3D(explosion3D,
                                           explosionSmoke3D,
                                           projectileSmoke3D);

            smokePlume3D = new SmokePlumeParticleSystem3D();
            smokePlume3D.Initialize();
            smokePlume3D.LoadContent();

            fire3D = new FireParticleSystem3D();
            fire3D.Initialize();
            fire3D.LoadContent();
        }

        public Vector3 RandomPointOnCircle()
        {
            const float radius = 5;

            double angle = random.NextDouble() * Math.PI * 2;

            float x = (float)Math.Cos(angle);
            float y = (float)Math.Sin(angle);

            return new Vector3(x * radius, 0, y * radius);
        }

    }
}
